﻿#region Usings

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

using DotNetNuke.Common;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security.Roles;
using DotNetNuke.Security.Roles.Internal;
using DotNetNuke.Services.Localization;
using DotNetNuke.Web.UI.WebControls;
using DotNetNuke.UI.WebControls;


#endregion

namespace WESNet.DNN.Controls.AdvancedRolesSelectionGrid
{
    [ToolboxData("<{0}:RolesSelectionGrid runat=server></{0}:RolesSelectionGrid>")]
    public class RolesSelectionGrid : Control, INamingContainer
    {
        private class RoleDTO
        {
            public int RoleID { get; set; }
            public string RoleName { get; set; }
            public string Description { get; set; }
            public SecurityMode SecurityMode { get; set; }
            public int UserCount { get; set; }
            public bool Selected { get; set; }

            public RoleDTO(RoleInfo roleInfo, bool selected)
            {
                RoleID = roleInfo.RoleID;
                RoleName = Localization.LocalizeRole(roleInfo.RoleName);
                Description = roleInfo.Description;
                SecurityMode = roleInfo.SecurityMode;
                UserCount = roleInfo.UserCount;
                Selected = selected;
            }
            
        }

		#region Private Members
        private HtmlGenericControl divRolesSelectionControl;
        private DropDownList ddlPortal;
        private HtmlGenericControl divRoleGroup;
        private DropDownList ddlRoleGroup;
        private RadioButtonList rblSecurityMode;
        private DataGrid dgRolesSelection;
        private LiteralControl litNoMatches;

        private List<PortalInfo> _Portals = null;
        private List<RoleGroupInfo> _RoleGroups = null;

        private List<string> _SelectedRoleNames = new List<string>();
        private List<RoleDTO> _Roles = new List<RoleDTO>();
		
		#endregion

		#region Public Properties

		#region DataGrid Properties


		public DataGridColumnCollection Columns
		{
			get
			{
				return dgRolesSelection.Columns;
			}
		}

		public DataGridItemCollection Items
		{
			get
			{
				return dgRolesSelection.Items;
			}
		}

		#endregion

		/// <summary>
		/// List of the Names of the selected Roles
		/// </summary>
		public List<string> SelectedRoleNames
		{
			get
			{
				UpdateSelectedRoleNames();
                return _SelectedRoleNames;
			}
			set
			{
                _SelectedRoleNames = value;
                BindData();
			}
		}

		 /// <summary>
		 /// Gets and Sets the LocalResourceFile to localize permissions
		 /// </summary>
        public string LocalResourceFile
        {
            get
            {
                return ViewState["LocalResourceFile"] == null ? Localization.SharedResourceFile : Convert.ToString(ViewState["LocalResourceFile"]);
            }
            set
            {
                ViewState["LocalResourceFile"] = value;
            }
        }

		/// <summary>
		/// Enable ShowAllUsers to display the virtual "Unauthenticated Users" role
		/// </summary>
        /// 

        public bool ShowPortalSelector
        {
            get
            {
                return ViewState["ShowPortalSelector"] == null ? false : Convert.ToBoolean(ViewState["ShowPortalSelector"]);
            }
            set
            {
                ViewState["ShowPortalSelector"] = value;
            }

        }

        public bool ShowRoleGroupSelector
        {
            get
            {
                return ViewState["ShowRoleGroupSelector"] == null ? true : Convert.ToBoolean(ViewState["ShowRoleGroupSelector"]);
            }
            set
            {
                ViewState["ShowRoleGroupSelector"] = value;
            }

        }

        public bool ShowSecurityModeSelector
        {
            get
            {
                return ViewState["ShowSecurityModeSelector"] == null ? false : Convert.ToBoolean(ViewState["ShowSecurityModeSelector"]);
            }
            set
            {
                ViewState["ShowSecurityModeSelector"] = value;
            }

        }

        public bool ShowDescription
        {
            get
            {
                return ViewState["ShowUDescription"] == null ? true : Convert.ToBoolean(ViewState["ShowDescription"]);
            }
            set
            {
                ViewState["ShowDescription"] = value;
            }
        }

        public bool ShowUserCount
        {
            get
            {
                return ViewState["ShowUserCount"] == null ? true : Convert.ToBoolean(ViewState["ShowUserCount"]);
            }
            set
            {
                ViewState["ShowUserCount"] = value;
            }
        }

		public bool ShowUnauthenticatedUsers
		{
			get
			{
			    return ViewState["ShowUnauthenticatedUsers"] == null ? false : Convert.ToBoolean(ViewState["ShowUnauthenticatedUsers"]); 
			}
		    set
			{
				ViewState["ShowUnauthenticatedUsers"] = value;
			}
		}

		/// <summary>
		/// Enable ShowAllUsers to display the virtuall "All Users" role
		/// </summary>
		public bool ShowAllUsers
		{
			get
			{
			    return ViewState["ShowAllUsers"] == null ? false : Convert.ToBoolean(ViewState["ShowAllUsers"]);
			}
		    set
			{
				ViewState["ShowAllUsers"] = value;
			}
		}

        public int PortalID
        {
            get
            {
                if ((ddlPortal != null) && (!string.IsNullOrEmpty(ddlPortal.SelectedValue)))
                {
                    return int.Parse(ddlPortal.SelectedValue);
                }
                else
                {
                    return ViewState["PortalID"] == null ? PortalController.Instance.GetCurrentPortalSettings().PortalId : Convert.ToInt32(ViewState["PortalID"]);
                }
            }
            set
            {
                EnsureChildControls();

                if (ddlPortal != null)
                {
                    ddlPortal.SelectedValue = value.ToString();
                }
                else
                {
                    ViewState["PortalID"] = value;
                }
            }
        }
		
        public int RoleGroupID
        {
            get
            {
                if ((ddlRoleGroup != null) && (!string.IsNullOrEmpty(ddlRoleGroup.SelectedValue)))
                {
                    return int.Parse(ddlRoleGroup.SelectedValue);
                }
                else
                {
                    return ViewState["RoleGroupID"] == null ? -2 : Convert.ToInt32(ViewState["RoleGroupID"]);
                }
            }
            set
            {
                EnsureChildControls();

                if (ddlRoleGroup != null)
                {
                    ddlRoleGroup.SelectedValue = value.ToString();
                }
                else
                {
                    ViewState["RoleGroupID"] = value;
                }
            }
        }

        public SecurityMode SecurityMode
        {
            get
            {
                if ((rblSecurityMode != null) && (!string.IsNullOrEmpty(rblSecurityMode.SelectedValue)))
                {
                    return (SecurityMode)(int.Parse(rblSecurityMode.SelectedValue));
                }
                else
                {
                    return ViewState["SecurityMode"] == null ? SecurityMode.SecurityRole : (SecurityMode)(Convert.ToInt32(ViewState["SecurityMode"]));
                }
            }
            set
            {
                EnsureChildControls();

                if (rblSecurityMode != null)
                {
                    rblSecurityMode.SelectedValue = value.ToString("d");
                }
                else
                {
                    ViewState["SecurityMode"] = value.ToString("d");
                }
            }
        }

        #endregion

        #region Private Properties

        private List<PortalInfo> Portals
        {
            get
            {
                if (_Portals == null)
                {
                    _Portals = new PortalController().GetPortals().Cast<PortalInfo>().ToList();
                }
                return _Portals;
            }
        }

        private List<RoleGroupInfo> RoleGroups
        {
            get
            {
                if (_RoleGroups == null)
                {
                    _RoleGroups = RoleController.GetRoleGroups(PortalID).Cast<RoleGroupInfo>().ToList();
                }
                return _RoleGroups;
            }
        }
        
#endregion

        #region Private Methods

        private void BindPortals()
        {
            if (ddlPortal != null)
            {
                ddlPortal.DataSource = Portals;
                ddlPortal.DataBind();
            }
        }

        private void BindRoleGroups()
        {
            if (ddlRoleGroup != null)
            {
                ddlRoleGroup.DataSource = RoleGroups;
                ddlRoleGroup.DataBind();
                if (ddlRoleGroup.Items.Count > 0)
                {
                    ddlRoleGroup.Items.Insert(0, new ListItem(Localization.GetString("GlobalRoles"), "-1"));
                    ddlRoleGroup.Items.Insert(0, new ListItem(Localization.GetString("AllRoles"), "-2") { Selected = true } ) ;
                    divRoleGroup.Visible = true;
                }
                else
                {
                    divRoleGroup.Visible = false;
                }
            }
        }


        /// <summary>
		/// Bind the data to the controls
		/// </summary>
		private void BindData()
		{
			EnsureChildControls();
            BindRolesGrid();
		}

		/// <summary>
		/// Bind the Roles data to the Grid
		/// </summary>
		private void BindRolesGrid()
		{
			
            _Roles = new List<RoleDTO>();
            foreach (RoleInfo role in GetRoles())
            {
                _Roles.Add(new RoleDTO(role, IsSelected(role.RoleName)));
            }

			UpdateSelectedRoleNames();
		    dgRolesSelection.DataSource = _Roles;
			dgRolesSelection.DataBind();

            dgRolesSelection.Visible = _Roles.Count > 0;
            litNoMatches.Visible = !dgRolesSelection.Visible;
		}

		private bool IsSelected (string roleName)
		{
		    return SelectedRoleNames.Any(r => r == roleName);
		}

	    /// <summary>
		/// Gets the roles from the Database and loads them into the Roles property
		/// </summary>
		private List<RoleInfo> GetRoles()
		{
            IList<RoleInfo> roles;
            var securityMode = SecurityMode;
               
            roles = RoleGroupID > -2 ? RoleController.Instance.GetRoles(PortalID, r => r.RoleGroupID == RoleGroupID && (r.SecurityMode == securityMode || securityMode==SecurityMode.Both) && r.Status == RoleStatus.Approved)
                                     : RoleController.Instance.GetRoles(PortalID, r => (r.SecurityMode == securityMode || securityMode == SecurityMode.Both) && r.Status == RoleStatus.Approved);
         
			
			if (RoleGroupID < 0 && securityMode != SecurityMode.SocialGroup)
			{
				if (ShowUnauthenticatedUsers)
				{
                    roles.Add(new RoleInfo { RoleID = int.Parse(Globals.glbRoleUnauthUser), RoleName = Globals.glbRoleUnauthUserName });
				}
				if (ShowAllUsers)
				{
                    roles.Add(new RoleInfo { RoleID = int.Parse(Globals.glbRoleAllUsers), RoleName = Globals.glbRoleAllUsersName });
				}
			}

			return roles.OrderBy(r => r.RoleName).ToList();
		}

		/// <summary>
		/// Sets up the columns for the Grid
		/// </summary>
		private void SetUpRolesGrid()
		{
			dgRolesSelection.Columns.Clear();
            
		    var idCol = new BoundColumn {HeaderText = "", DataField = "RoleId", Visible = false};
		    dgRolesSelection.Columns.Add(idCol);

            var columnTemplate = new CheckBoxColumnTemplate {DataField = "Selected"};
            var checkCol = new TemplateColumn();
		    checkCol.ItemTemplate = columnTemplate;
			dgRolesSelection.Columns.Add(checkCol);

            var nameCol = new BoundColumn() { HeaderText = Localization.GetString("RoleName.Header", LocalResourceFile), DataField = "RoleName" };
		    dgRolesSelection.Columns.Add(nameCol);

            if (ShowDescription)
            {
                var descCol = new BoundColumn() { HeaderText = Localization.GetString("Description.Header", LocalResourceFile), DataField = "Description" };
                descCol.ItemStyle.CssClass = "Description";
                dgRolesSelection.Columns.Add(descCol);
            }

            if (ShowSecurityModeSelector)
            {
                var securityModeCol = new BoundColumn() { HeaderText = Localization.GetString("SecurityMode.Header", LocalResourceFile), DataField = "SecurityMode" };
                dgRolesSelection.Columns.Add(securityModeCol);
            }

            if (ShowUserCount)
            {
                var userCountCol = new BoundColumn() { HeaderText = Localization.GetString("UserCount.Header", LocalResourceFile), DataField = "UserCount" };
                 dgRolesSelection.Columns.Add(userCountCol);
            }


		}

        private Control AddField(Control parent, string id, WebControl fieldControl)
        {
            var divControl = new HtmlGenericControl("div");
            divControl.Attributes.Add("class", "dnnFormItem");
            var label = new Label();
            label.ID = "pl" + id;
            label.AssociatedControlID = "ctl" + id;
            label.Text = Localization.GetString(label.ID, LocalResourceFile);
            label.Attributes.Add("class", "dnnLabel");
            divControl.Controls.Add(label);
            divControl.Controls.Add(new LiteralControl("&nbsp;&nbsp;"));
            fieldControl.ID = "ctl" + id;
            divControl.Controls.Add(fieldControl);
            parent.Controls.Add(divControl);
            return divControl;
        }

		#endregion

		#region Protected Methods

        ///// <summary>
        ///// Load the ViewState
        ///// </summary>
        ///// <param name="savedState">The saved state</param>
        //protected override void LoadViewState(object savedState)
        //{
        //    if (savedState != null)
        //    {
        //        //Load State from the array of objects that was saved with SaveViewState.
        //        var myState = (object[]) savedState;
				
        //        //Load Base Controls ViewState
        //        if (myState[0] != null)
        //        {
        //            base.LoadViewState(myState[0]);
        //        }
				
        //        //Load TabPermissions
        //        if (myState[1] != null)
        //        {
        //            string state = Convert.ToString(myState[1]);
        //            CurrentRoleSelection = state != string.Empty 
        //                                ? new List<string>(state.Split(new[] {"##"}, StringSplitOptions.None)) 
        //                                : new List<string>();
        //        }
        //    }
        //}

        ///// <summary>
        ///// Saves the ViewState
        ///// </summary>
        //protected override object SaveViewState()
        //{
        //    var allStates = new object[2];

        //    //Save the Base Controls ViewState
        //    allStates[0] = base.SaveViewState();
        //    //Persist the TabPermisisons
        //    var sb = new StringBuilder();
        //    bool addDelimiter = false;
        //    foreach (string role in CurrentRoleSelection)
        //    {
        //        if (addDelimiter)
        //        {
        //            sb.Append("##");
        //        }
        //        else
        //        {
        //            addDelimiter = true;
        //        }
        //        sb.Append(role);
        //    }
        //    allStates[1] = sb.ToString();
        //    return allStates;
        //}

        /// <summary>
		/// Creates the Child Controls
		/// </summary>
		protected override void CreateChildControls()
		{
		    divRolesSelectionControl = new System.Web.UI.HtmlControls.HtmlGenericControl("div");
            divRolesSelectionControl.Attributes.Add("class", "AdvancedRolesSelectionGrid");

            if (ShowPortalSelector && UserController.Instance.GetCurrentUserInfo().IsSuperUser)
            {
                if (Portals.Count > 1)
                {
                    ddlPortal = new DropDownList() { AutoPostBack = true, DataTextField = "PortalName", DataValueField = "PortalID" };
                    AddField(divRolesSelectionControl, "Portal", ddlPortal);
                }
            }         

			if (ShowRoleGroupSelector)
            {
                ddlRoleGroup = new DropDownList() { AutoPostBack = true, DataTextField = "RoleGroupName", DataValueField = "RoleGroupID" };
                divRoleGroup = (HtmlGenericControl)AddField(divRolesSelectionControl, "RoleGroup", ddlRoleGroup);
                BindRoleGroups();
			}

            if (ShowSecurityModeSelector)
            {
                rblSecurityMode = new RadioButtonList() { AutoPostBack = true, RepeatDirection = RepeatDirection.Horizontal, CssClass = "dnnFormRadioButtons" };
                rblSecurityMode.Items.Add(new ListItem(Localization.GetString("SecurityRole", LocalResourceFile), SecurityMode.SecurityRole.ToString("d")));
                rblSecurityMode.Items.Add(new ListItem(Localization.GetString("SocialGroup", LocalResourceFile), SecurityMode.SocialGroup.ToString("d")));
                rblSecurityMode.Items.Add(new ListItem(Localization.GetString("Both", LocalResourceFile), SecurityMode.Both.ToString("d")));
                rblSecurityMode.SelectedValue = "0";
                AddField(divRolesSelectionControl, "SecurityMode", rblSecurityMode);
            }

		    dgRolesSelection = new DataGrid {AutoGenerateColumns = false, CellSpacing = 0, GridLines = GridLines.None, CssClass="dnnGrid"};
		    dgRolesSelection.FooterStyle.CssClass = "dnnGridFooter";
			dgRolesSelection.HeaderStyle.CssClass = "dnnGridHeader";
			dgRolesSelection.ItemStyle.CssClass = "dnnGridItem";
			dgRolesSelection.AlternatingItemStyle.CssClass = "dnnGridAltItem";
            dgRolesSelection.ID = "ctlRoles";
            divRolesSelectionControl.Controls.Add(dgRolesSelection);
            litNoMatches = new LiteralControl(Localization.GetString("NoMatchingRoles", LocalResourceFile)) {Visible = false };
            divRolesSelectionControl.Controls.Add(litNoMatches);

			SetUpRolesGrid();
            
			Controls.Add(divRolesSelectionControl);
            ChildControlsCreated = true;
		}

		/// <summary>
		/// Overrides the base OnPreRender method to Bind the Grid to the Permissions
		/// </summary>
		/// <history>
		///     [cnurse]    01/09/2006  Documented
		/// </history>
		protected override void OnPreRender(EventArgs e)
		{
			BindData();
		}

		

		/// <summary>
		/// Updates the Selections
		/// </summary>
		protected void UpdateSelections()
		{
			EnsureChildControls();
            UpdateSelectedRoleNames();
		}

		/// <summary>
		/// Updates the permissions
		/// </summary>
		protected void UpdateSelectedRoleNames()
		{
			if (dgRolesSelection != null)
			{
				foreach (DataGridItem dgi in dgRolesSelection.Items)
				{
				    if (dgi.Cells[1].Controls.Count > 0)
					{
						var cb = (CheckBox) dgi.Cells[1].Controls[0];
						UpdateSelectedRoleName(dgi.Cells[2].Text, cb.Checked);
					}
				}
			}
		}

        /// <summary>
        /// Updates a Selection
        /// </summary>
        /// <param name="roleName">The name of the role</param>
        /// <param name="Selected"></param>
        protected virtual void UpdateSelectedRoleName(string roleName, bool Selected)
        {
            var isMatch = false;
            foreach (string currentRoleName in _SelectedRoleNames)
            {
                if (currentRoleName == roleName)
                {
                    //role is in collection
                    if (!Selected)
                    {
                        //Remove from collection as we only keep selected roles
                        _SelectedRoleNames.Remove(currentRoleName);
                    }
                    isMatch = true;
                    break;
                }
            }

            //Rolename not found so add new
            if (!isMatch && Selected)
            {
                _SelectedRoleNames.Add(roleName);
            }
        }

		#endregion

    }
}
